"""PersistentVolumeClaim资源提取器模块"""

from typing import Dict, Any, Optional, List
import yaml
import logging
from src.extractors.base import Extractor

class PersistentVolumeClaimExtractor(Extractor):
    """
    PersistentVolumeClaim资源提取器
    负责从PersistentVolumeClaim资源定义中提取关键信息
    """
    
    def __init__(self, logger: Optional[logging.Logger] = None):
        """初始化PersistentVolumeClaim提取器"""
        super().__init__(logger)
        self.resource_type = "PersistentVolumeClaim"
    
    def extract(self, content: str, file_path: str = "") -> Dict[str, Any]:
        """
        从PersistentVolumeClaim YAML/JSON内容中提取信息
        
        Args:
            content: YAML/JSON格式的资源内容
            file_path: 资源文件路径，可选，用于日志记录
            
        Returns:
            提取的PersistentVolumeClaim资源信息字典
        """
        # 解析YAML/JSON内容
        resource = self.parse_content(content, file_path)
        if not resource:
            return {}
            
        # 检查是否为PersistentVolumeClaim资源
        if resource.get("kind") != "PersistentVolumeClaim":
            self.logger.warning(f"资源不是PersistentVolumeClaim: {file_path}")
            return {}
            
        # 提取基本信息
        result = self._extract_basic_info(resource)
        
        # 提取规格信息
        self._extract_spec(resource, result)
        
        # 提取状态信息
        self._extract_status(resource, result)
        
        return result
    
    def _extract_basic_info(self, resource: Dict[str, Any]) -> Dict[str, Any]:
        """
        提取基本元数据信息
        
        Args:
            resource: 解析后的资源字典
            
        Returns:
            包含基本信息的字典
        """
        metadata = resource.get("metadata", {})
        
        result = {
            "kind": "PersistentVolumeClaim",
            "name": metadata.get("name", ""),
            "namespace": metadata.get("namespace", "default"),
            "creation_timestamp": metadata.get("creationTimestamp", "")
        }
        
        # 提取标签和注解
        if "labels" in metadata:
            result["labels"] = metadata.get("labels", {})
            
        if "annotations" in metadata:
            result["annotations"] = metadata.get("annotations", {})
            
        # 提取卷名称（绑定的PV）
        if "volumeName" in metadata:
            result["volume_name"] = metadata.get("volumeName")
            
        # 提取存储类名称（可能在注解中）
        storage_class_annotation = "volume.beta.kubernetes.io/storage-class"
        if "annotations" in metadata and storage_class_annotation in metadata.get("annotations", {}):
            result["storage_class_annotation"] = metadata.get("annotations", {}).get(storage_class_annotation)
            
        return result
    
    def _extract_spec(self, resource: Dict[str, Any], result: Dict[str, Any]) -> None:
        """
        提取PVC规格信息
        
        Args:
            resource: 解析后的资源字典
            result: 要填充的结果字典
        """
        spec = resource.get("spec", {})
        
        if not spec:
            return
            
        # 提取访问模式
        if "accessModes" in spec:
            result["access_modes"] = spec.get("accessModes", [])
            
        # 提取卷模式（Filesystem 或 Block）
        if "volumeMode" in spec:
            result["volume_mode"] = spec.get("volumeMode")
            
        # 提取资源请求（存储大小）
        if "resources" in spec:
            resources = spec.get("resources", {})
            result["resources"] = {}
            
            if "requests" in resources:
                result["resources"]["requests"] = resources.get("requests", {})
                
            if "limits" in resources:
                result["resources"]["limits"] = resources.get("limits", {})
                
        # 提取存储类名称
        if "storageClassName" in spec:
            result["storage_class_name"] = spec.get("storageClassName", "")
            
        # 提取卷名称
        if "volumeName" in spec:
            result["volume_name"] = spec.get("volumeName")
            
        # 提取选择器
        if "selector" in spec:
            selector = spec.get("selector", {})
            result["selector"] = {}
            
            if "matchLabels" in selector:
                result["selector"]["match_labels"] = selector.get("matchLabels", {})
                
            if "matchExpressions" in selector:
                match_expressions = []
                for expr in selector.get("matchExpressions", []):
                    match_expressions.append({
                        "key": expr.get("key", ""),
                        "operator": expr.get("operator", ""),
                        "values": expr.get("values", [])
                    })
                
                result["selector"]["match_expressions"] = match_expressions
                
        # 提取数据源（用于克隆PVC或从快照恢复）
        if "dataSource" in spec:
            data_source = spec.get("dataSource", {})
            result["data_source"] = {
                "name": data_source.get("name", ""),
                "kind": data_source.get("kind", ""),
            }
            
            if "apiGroup" in data_source:
                result["data_source"]["api_group"] = data_source.get("apiGroup")
                
        # 提取数据源参考（K8s 1.22+）
        if "dataSourceRef" in spec:
            data_source_ref = spec.get("dataSourceRef", {})
            result["data_source_ref"] = {
                "name": data_source_ref.get("name", ""),
                "kind": data_source_ref.get("kind", ""),
            }
            
            if "apiGroup" in data_source_ref:
                result["data_source_ref"]["api_group"] = data_source_ref.get("apiGroup")
    
    def _extract_status(self, resource: Dict[str, Any], result: Dict[str, Any]) -> None:
        """
        提取PVC状态信息
        
        Args:
            resource: 解析后的资源字典
            result: 要填充的结果字典
        """
        status = resource.get("status", {})
        
        if not status:
            return
            
        result["status"] = {}
        
        # 提取阶段（Pending, Bound, Lost）
        if "phase" in status:
            result["status"]["phase"] = status.get("phase")
            
        # 提取访问模式
        if "accessModes" in status:
            result["status"]["access_modes"] = status.get("accessModes", [])
            
        # 提取容量
        if "capacity" in status:
            result["status"]["capacity"] = status.get("capacity", {})
            
        # 提取条件
        if "conditions" in status:
            conditions = []
            for condition in status.get("conditions", []):
                conditions.append(self._clean_keys(condition))
                
            if conditions:
                result["status"]["conditions"] = conditions
    
    def _to_snake_case(self, camel_case: str) -> str:
        """
        将驼峰命名转换为蛇形命名
        
        Args:
            camel_case: 驼峰命名的字符串
            
        Returns:
            蛇形命名的字符串
        """
        snake_case = ""
        for i, char in enumerate(camel_case):
            if char.isupper():
                if i > 0:
                    snake_case += "_"
                snake_case += char.lower()
            else:
                snake_case += char
        return snake_case
    
    def _clean_keys(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """
        递归清理字典键为蛇形命名
        
        Args:
            data: 要清理的字典
            
        Returns:
            清理后的字典
        """
        result = {}
        
        if not isinstance(data, dict):
            return data
            
        for key, value in data.items():
            new_key = self._to_snake_case(key)
            
            if isinstance(value, dict):
                result[new_key] = self._clean_keys(value)
            elif isinstance(value, list):
                result[new_key] = [
                    self._clean_keys(item) if isinstance(item, dict) else item
                    for item in value
                ]
            else:
                result[new_key] = value
                
        return result
    
    def parse_content(self, content: str, file_path: str = "") -> Dict[str, Any]:
        """
        解析YAML/JSON内容
        
        Args:
            content: YAML/JSON格式的字符串内容
            file_path: 文件路径，用于记录日志
            
        Returns:
            解析后的字典
        """
        if isinstance(content, dict):
            return content
            
        try:
            return yaml.safe_load(content) or {}
        except yaml.YAMLError as e:
            self.logger.error(f"解析YAML失败: {file_path}, 错误: {str(e)}")
            return {}